home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 23 Character Animation / SkinnedMesh / SkinnedMeshApp.cpp < prev    next >
C/C++ Source or Header  |  2016-03-02  |  78KB  |  1,963 lines

  1. //***************************************************************************************
  2. // SkinnedMeshApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "../../Common/Camera.h"
  10. #include "FrameResource.h"
  11. #include "ShadowMap.h"
  12. #include "Ssao.h"
  13. #include "SkinnedData.h"
  14. #include "LoadM3d.h"
  15.  
  16. using Microsoft::WRL::ComPtr;
  17. using namespace DirectX;
  18. using namespace DirectX::PackedVector;
  19.  
  20. const int gNumFrameResources = 3;
  21.  
  22. struct SkinnedModelInstance
  23. {
  24.     SkinnedData* SkinnedInfo = nullptr;
  25.     std::vector<DirectX::XMFLOAT4X4> FinalTransforms;
  26.     std::string ClipName;
  27.     float TimePos = 0.0f;
  28.  
  29.     // Called every frame and increments the time position, interpolates the 
  30.     // animations for each bone based on the current animation clip, and 
  31.     // generates the final transforms which are ultimately set to the effect
  32.     // for processing in the vertex shader.
  33.     void UpdateSkinnedAnimation(float dt)
  34.     {
  35.         TimePos += dt;
  36.  
  37.         // Loop animation
  38.         if(TimePos > SkinnedInfo->GetClipEndTime(ClipName))
  39.             TimePos = 0.0f;
  40.  
  41.         // Compute the final transforms for this time position.
  42.         SkinnedInfo->GetFinalTransforms(ClipName, TimePos, FinalTransforms);
  43.     }
  44. };
  45.  
  46. // Lightweight structure stores parameters to draw a shape.  This will
  47. // vary from app-to-app.
  48. struct RenderItem
  49. {
  50.     RenderItem() = default;
  51.     RenderItem(const RenderItem& rhs) = delete;
  52.  
  53.     // World matrix of the shape that describes the object's local space
  54.     // relative to the world space, which defines the position, orientation,
  55.     // and scale of the object in the world.
  56.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  57.  
  58.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  59.  
  60.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  61.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  62.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  63.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  64.     int NumFramesDirty = gNumFrameResources;
  65.  
  66.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  67.     UINT ObjCBIndex = -1;
  68.  
  69.     Material* Mat = nullptr;
  70.     MeshGeometry* Geo = nullptr;
  71.  
  72.     // Primitive topology.
  73.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  74.  
  75.     // DrawIndexedInstanced parameters.
  76.     UINT IndexCount = 0;
  77.     UINT StartIndexLocation = 0;
  78.     int BaseVertexLocation = 0;
  79.     
  80.     // Only applicable to skinned render-items.
  81.     UINT SkinnedCBIndex = -1;
  82.     
  83.     // nullptr if this render-item is not animated by skinned mesh.
  84.     SkinnedModelInstance* SkinnedModelInst = nullptr;
  85. };
  86.  
  87. enum class RenderLayer : int
  88. {
  89.     Opaque = 0,
  90.     SkinnedOpaque,
  91.     Debug,
  92.     Sky,
  93.     Count
  94. };
  95.  
  96. class SkinnedMeshApp : public D3DApp
  97. {
  98. public:
  99.     SkinnedMeshApp(HINSTANCE hInstance);
  100.     SkinnedMeshApp(const SkinnedMeshApp& rhs) = delete;
  101.     SkinnedMeshApp& operator=(const SkinnedMeshApp& rhs) = delete;
  102.     ~SkinnedMeshApp();
  103.  
  104.     virtual bool Initialize()override;
  105.  
  106. private:
  107.     virtual void CreateRtvAndDsvDescriptorHeaps()override;
  108.     virtual void OnResize()override;
  109.     virtual void Update(const GameTimer& gt)override;
  110.     virtual void Draw(const GameTimer& gt)override;
  111.  
  112.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  113.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  114.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  115.  
  116.     void OnKeyboardInput(const GameTimer& gt);
  117.     void AnimateMaterials(const GameTimer& gt);
  118.     void UpdateObjectCBs(const GameTimer& gt);
  119.     void UpdateSkinnedCBs(const GameTimer& gt);
  120.     void UpdateMaterialBuffer(const GameTimer& gt);
  121.     void UpdateShadowTransform(const GameTimer& gt);
  122.     void UpdateMainPassCB(const GameTimer& gt);
  123.     void UpdateShadowPassCB(const GameTimer& gt);
  124.     void UpdateSsaoCB(const GameTimer& gt);
  125.  
  126.     void LoadTextures();
  127.     void BuildRootSignature();
  128.     void BuildSsaoRootSignature();
  129.     void BuildDescriptorHeaps();
  130.     void BuildShadersAndInputLayout();
  131.     void BuildShapeGeometry();
  132.     void LoadSkinnedModel();
  133.     void BuildPSOs();
  134.     void BuildFrameResources();
  135.     void BuildMaterials();
  136.     void BuildRenderItems();
  137.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  138.     void DrawSceneToShadowMap();
  139.     void DrawNormalsAndDepth();
  140.  
  141.     CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuSrv(int index)const;
  142.     CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuSrv(int index)const;
  143.     CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(int index)const;
  144.     CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(int index)const;
  145.  
  146.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> GetStaticSamplers();
  147.  
  148. private:
  149.  
  150.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  151.     FrameResource* mCurrFrameResource = nullptr;
  152.     int mCurrFrameResourceIndex = 0;
  153.  
  154.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  155.     ComPtr<ID3D12RootSignature> mSsaoRootSignature = nullptr;
  156.  
  157.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  158.  
  159.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  160.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  161.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  162.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  163.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  164.  
  165.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  166.     std::vector<D3D12_INPUT_ELEMENT_DESC> mSkinnedInputLayout;
  167.  
  168.     // List of all the render items.
  169.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  170.  
  171.     // Render items divided by PSO.
  172.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  173.  
  174.     UINT mSkyTexHeapIndex = 0;
  175.     UINT mShadowMapHeapIndex = 0;
  176.     UINT mSsaoHeapIndexStart = 0;
  177.     UINT mSsaoAmbientMapIndex = 0;
  178.  
  179.     UINT mNullCubeSrvIndex = 0;
  180.     UINT mNullTexSrvIndex1 = 0;
  181.     UINT mNullTexSrvIndex2 = 0;
  182.  
  183.     CD3DX12_GPU_DESCRIPTOR_HANDLE mNullSrv;
  184.  
  185.     PassConstants mMainPassCB;  // index 0 of pass cbuffer.
  186.     PassConstants mShadowPassCB;// index 1 of pass cbuffer.
  187.  
  188.     UINT mSkinnedSrvHeapStart = 0;
  189.     std::string mSkinnedModelFilename = "Models\\soldier.m3d";
  190.     std::unique_ptr<SkinnedModelInstance> mSkinnedModelInst; 
  191.     SkinnedData mSkinnedInfo;
  192.     std::vector<M3DLoader::Subset> mSkinnedSubsets;
  193.     std::vector<M3DLoader::M3dMaterial> mSkinnedMats;
  194.     std::vector<std::string> mSkinnedTextureNames;
  195.  
  196.     Camera mCamera;
  197.  
  198.     std::unique_ptr<ShadowMap> mShadowMap;
  199.  
  200.     std::unique_ptr<Ssao> mSsao;
  201.  
  202.     DirectX::BoundingSphere mSceneBounds;
  203.  
  204.     float mLightNearZ = 0.0f;
  205.     float mLightFarZ = 0.0f;
  206.     XMFLOAT3 mLightPosW;
  207.     XMFLOAT4X4 mLightView = MathHelper::Identity4x4();
  208.     XMFLOAT4X4 mLightProj = MathHelper::Identity4x4();
  209.     XMFLOAT4X4 mShadowTransform = MathHelper::Identity4x4();
  210.  
  211.     float mLightRotationAngle = 0.0f;
  212.     XMFLOAT3 mBaseLightDirections[3] = {
  213.         XMFLOAT3(0.57735f, -0.57735f, 0.57735f),
  214.         XMFLOAT3(-0.57735f, -0.57735f, 0.57735f),
  215.         XMFLOAT3(0.0f, -0.707f, -0.707f)
  216.     };
  217.     XMFLOAT3 mRotatedLightDirections[3];
  218.  
  219.     POINT mLastMousePos;
  220. };
  221.  
  222. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  223.     PSTR cmdLine, int showCmd)
  224. {
  225.     // Enable run-time memory check for debug builds.
  226. #if defined(DEBUG) | defined(_DEBUG)
  227.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  228. #endif
  229.  
  230.     try
  231.     {
  232.         SkinnedMeshApp theApp(hInstance);
  233.         if(!theApp.Initialize())
  234.             return 0;
  235.  
  236.         return theApp.Run();
  237.     }
  238.     catch(DxException& e)
  239.     {
  240.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  241.         return 0;
  242.     }
  243. }
  244.  
  245. SkinnedMeshApp::SkinnedMeshApp(HINSTANCE hInstance)
  246.     : D3DApp(hInstance)
  247. {
  248.     // Estimate the scene bounding sphere manually since we know how the scene was constructed.
  249.     // The grid is the "widest object" with a width of 20 and depth of 30.0f, and centered at
  250.     // the world space origin.  In general, you need to loop over every world space vertex
  251.     // position and compute the bounding sphere.
  252.     mSceneBounds.Center = XMFLOAT3(0.0f, 0.0f, 0.0f);
  253.     mSceneBounds.Radius = sqrtf(10.0f*10.0f + 15.0f*15.0f);
  254. }
  255.  
  256. SkinnedMeshApp::~SkinnedMeshApp()
  257. {
  258.     if(md3dDevice != nullptr)
  259.         FlushCommandQueue();
  260. }
  261.  
  262. bool SkinnedMeshApp::Initialize()
  263. {
  264.     if(!D3DApp::Initialize())
  265.         return false;
  266.  
  267.     // Reset the command list to prep for initialization commands.
  268.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  269.  
  270.     mCamera.SetPosition(0.0f, 2.0f, -15.0f);
  271.  
  272.     mShadowMap = std::make_unique<ShadowMap>(md3dDevice.Get(),
  273.         2048, 2048);
  274.  
  275.     mSsao = std::make_unique<Ssao>(
  276.         md3dDevice.Get(),
  277.         mCommandList.Get(),
  278.         mClientWidth, mClientHeight);
  279.  
  280.     LoadSkinnedModel();
  281.     LoadTextures();
  282.     BuildRootSignature();
  283.     BuildSsaoRootSignature();
  284.     BuildDescriptorHeaps();
  285.     BuildShadersAndInputLayout();
  286.     BuildShapeGeometry();
  287.     BuildMaterials();
  288.     BuildRenderItems();
  289.     BuildFrameResources();
  290.     BuildPSOs();
  291.  
  292.     mSsao->SetPSOs(mPSOs["ssao"].Get(), mPSOs["ssaoBlur"].Get());
  293.  
  294.     // Execute the initialization commands.
  295.     ThrowIfFailed(mCommandList->Close());
  296.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  297.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  298.  
  299.     // Wait until initialization is complete.
  300.     FlushCommandQueue();
  301.  
  302.     return true;
  303. }
  304.  
  305. void SkinnedMeshApp::CreateRtvAndDsvDescriptorHeaps()
  306. {
  307.     // Add +1 for screen normal map, +2 for ambient maps.
  308.     D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
  309.     rtvHeapDesc.NumDescriptors = SwapChainBufferCount + 3;
  310.     rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
  311.     rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  312.     rtvHeapDesc.NodeMask = 0;
  313.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  314.         &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));
  315.  
  316.     // Add +1 DSV for shadow map.
  317.     D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
  318.     dsvHeapDesc.NumDescriptors = 2;
  319.     dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
  320.     dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  321.     dsvHeapDesc.NodeMask = 0;
  322.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  323.         &dsvHeapDesc, IID_PPV_ARGS(mDsvHeap.GetAddressOf())));
  324. }
  325.  
  326. void SkinnedMeshApp::OnResize()
  327. {
  328.     D3DApp::OnResize();
  329.  
  330.     mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  331.  
  332.     if(mSsao != nullptr)
  333.     {
  334.         mSsao->OnResize(mClientWidth, mClientHeight);
  335.  
  336.         // Resources changed, so need to rebuild descriptors.
  337.         mSsao->RebuildDescriptors(mDepthStencilBuffer.Get());
  338.     }
  339. }
  340.  
  341. void SkinnedMeshApp::Update(const GameTimer& gt)
  342. {
  343.     OnKeyboardInput(gt);
  344.  
  345.     // Cycle through the circular frame resource array.
  346.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  347.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  348.  
  349.     // Has the GPU finished processing the commands of the current frame resource?
  350.     // If not, wait until the GPU has completed commands up to this fence point.
  351.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  352.     {
  353.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  354.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  355.         WaitForSingleObject(eventHandle, INFINITE);
  356.         CloseHandle(eventHandle);
  357.     }
  358.  
  359.     //
  360.     // Animate the lights (and hence shadows).
  361.     //
  362.  
  363.     mLightRotationAngle += 0.1f*gt.DeltaTime();
  364.  
  365.     XMMATRIX R = XMMatrixRotationY(mLightRotationAngle);
  366.     for(int i = 0; i < 3; ++i)
  367.     {
  368.         XMVECTOR lightDir = XMLoadFloat3(&mBaseLightDirections[i]);
  369.         lightDir = XMVector3TransformNormal(lightDir, R);
  370.         XMStoreFloat3(&mRotatedLightDirections[i], lightDir);
  371.     }
  372.  
  373.     AnimateMaterials(gt);
  374.     UpdateObjectCBs(gt);
  375.     UpdateSkinnedCBs(gt);
  376.     UpdateMaterialBuffer(gt);
  377.     UpdateShadowTransform(gt);
  378.     UpdateMainPassCB(gt);
  379.     UpdateShadowPassCB(gt);
  380.     UpdateSsaoCB(gt);
  381. }
  382.  
  383. void SkinnedMeshApp::Draw(const GameTimer& gt)
  384. {
  385.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  386.  
  387.     // Reuse the memory associated with command recording.
  388.     // We can only reset when the associated command lists have finished execution on the GPU.
  389.     ThrowIfFailed(cmdListAlloc->Reset());
  390.  
  391.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  392.     // Reusing the command list reuses memory.
  393.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  394.  
  395.     ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
  396.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  397.  
  398.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  399.  
  400.     //
  401.     // Shadow map pass.
  402.     //
  403.  
  404.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  405.     // set as a root descriptor.
  406.     auto matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  407.     mCommandList->SetGraphicsRootShaderResourceView(3, matBuffer->GetGPUVirtualAddress());
  408.     
  409.     // Bind null SRV for shadow map pass.
  410.     mCommandList->SetGraphicsRootDescriptorTable(4, mNullSrv);     
  411.  
  412.     // Bind all the textures used in this scene.  Observe
  413.     // that we only have to specify the first descriptor in the table.  
  414.     // The root signature knows how many descriptors are expected in the table.
  415.     mCommandList->SetGraphicsRootDescriptorTable(5, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  416.  
  417.     DrawSceneToShadowMap();
  418.  
  419.     //
  420.     // Normal/depth pass.
  421.     //
  422.     
  423.     DrawNormalsAndDepth();
  424.     
  425.     //
  426.     //
  427.     // 
  428.     
  429.     mCommandList->SetGraphicsRootSignature(mSsaoRootSignature.Get());
  430.     mSsao->ComputeSsao(mCommandList.Get(), mCurrFrameResource, 2);
  431.     
  432.     //
  433.     // Main rendering pass.
  434.     //
  435.     
  436.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  437.  
  438.     // Rebind state whenever graphics root signature changes.
  439.  
  440.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  441.     // set as a root descriptor.
  442.     matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  443.     mCommandList->SetGraphicsRootShaderResourceView(3, matBuffer->GetGPUVirtualAddress());
  444.  
  445.  
  446.     mCommandList->RSSetViewports(1, &mScreenViewport);
  447.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  448.  
  449.     // Indicate a state transition on the resource usage.
  450.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  451.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  452.  
  453.     // Clear the back buffer and depth buffer.
  454.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  455.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  456.  
  457.     // Specify the buffers we are going to render to.
  458.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  459.  
  460.     // Bind all the textures used in this scene.  Observe
  461.     // that we only have to specify the first descriptor in the table.  
  462.     // The root signature knows how many descriptors are expected in the table.
  463.     mCommandList->SetGraphicsRootDescriptorTable(5, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  464.     
  465.     auto passCB = mCurrFrameResource->PassCB->Resource();
  466.     mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
  467.  
  468.     // Bind the sky cube map.  For our demos, we just use one "world" cube map representing the environment
  469.     // from far away, so all objects will use the same cube map and we only need to set it once per-frame.  
  470.     // If we wanted to use "local" cube maps, we would have to change them per-object, or dynamically
  471.     // index into an array of cube maps.
  472.  
  473.     CD3DX12_GPU_DESCRIPTOR_HANDLE skyTexDescriptor(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  474.     skyTexDescriptor.Offset(mSkyTexHeapIndex, mCbvSrvUavDescriptorSize);
  475.     mCommandList->SetGraphicsRootDescriptorTable(4, skyTexDescriptor);
  476.  
  477.     mCommandList->SetPipelineState(mPSOs["opaque"].Get());
  478.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  479.  
  480.     mCommandList->SetPipelineState(mPSOs["skinnedOpaque"].Get());
  481.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::SkinnedOpaque]);
  482.  
  483.     mCommandList->SetPipelineState(mPSOs["debug"].Get());
  484.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Debug]);
  485.  
  486.     mCommandList->SetPipelineState(mPSOs["sky"].Get());
  487.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Sky]);
  488.  
  489.     // Indicate a state transition on the resource usage.
  490.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  491.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  492.  
  493.     // Done recording commands.
  494.     ThrowIfFailed(mCommandList->Close());
  495.  
  496.     // Add the command list to the queue for execution.
  497.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  498.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  499.  
  500.     // Swap the back and front buffers
  501.     ThrowIfFailed(mSwapChain->Present(0, 0));
  502.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  503.  
  504.     // Advance the fence value to mark commands up to this fence point.
  505.     mCurrFrameResource->Fence = ++mCurrentFence;
  506.  
  507.     // Add an instruction to the command queue to set a new fence point. 
  508.     // Because we are on the GPU timeline, the new fence point won't be 
  509.     // set until the GPU finishes processing all the commands prior to this Signal().
  510.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  511. }
  512.  
  513. void SkinnedMeshApp::OnMouseDown(WPARAM btnState, int x, int y)
  514. {
  515.     mLastMousePos.x = x;
  516.     mLastMousePos.y = y;
  517.  
  518.     SetCapture(mhMainWnd);
  519. }
  520.  
  521. void SkinnedMeshApp::OnMouseUp(WPARAM btnState, int x, int y)
  522. {
  523.     ReleaseCapture();
  524. }
  525.  
  526. void SkinnedMeshApp::OnMouseMove(WPARAM btnState, int x, int y)
  527. {
  528.     if((btnState & MK_LBUTTON) != 0)
  529.     {
  530.         // Make each pixel correspond to a quarter of a degree.
  531.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  532.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  533.  
  534.         mCamera.Pitch(dy);
  535.         mCamera.RotateY(dx);
  536.     }
  537.  
  538.     mLastMousePos.x = x;
  539.     mLastMousePos.y = y;
  540. }
  541.  
  542. void SkinnedMeshApp::OnKeyboardInput(const GameTimer& gt)
  543. {
  544.     const float dt = gt.DeltaTime();
  545.  
  546.     if(GetAsyncKeyState('W') & 0x8000)
  547.         mCamera.Walk(10.0f*dt);
  548.  
  549.     if(GetAsyncKeyState('S') & 0x8000)
  550.         mCamera.Walk(-10.0f*dt);
  551.  
  552.     if(GetAsyncKeyState('A') & 0x8000)
  553.         mCamera.Strafe(-10.0f*dt);
  554.  
  555.     if(GetAsyncKeyState('D') & 0x8000)
  556.         mCamera.Strafe(10.0f*dt);
  557.  
  558.     mCamera.UpdateViewMatrix();
  559. }
  560.  
  561. void SkinnedMeshApp::AnimateMaterials(const GameTimer& gt)
  562. {
  563.     
  564. }
  565.  
  566. void SkinnedMeshApp::UpdateObjectCBs(const GameTimer& gt)
  567. {
  568.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  569.     for(auto& e : mAllRitems)
  570.     {
  571.         // Only update the cbuffer data if the constants have changed.  
  572.         // This needs to be tracked per frame resource.
  573.         if(e->NumFramesDirty > 0)
  574.         {
  575.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  576.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  577.  
  578.             ObjectConstants objConstants;
  579.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  580.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  581.             objConstants.MaterialIndex = e->Mat->MatCBIndex;
  582.  
  583.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  584.  
  585.             // Next FrameResource need to be updated too.
  586.             e->NumFramesDirty--;
  587.         }
  588.     }
  589. }
  590.  
  591. void SkinnedMeshApp::UpdateSkinnedCBs(const GameTimer& gt)
  592. {
  593.     auto currSkinnedCB = mCurrFrameResource->SkinnedCB.get();
  594.    
  595.     // We only have one skinned model being animated.
  596.     mSkinnedModelInst->UpdateSkinnedAnimation(gt.DeltaTime());
  597.         
  598.     SkinnedConstants skinnedConstants;
  599.     std::copy(
  600.         std::begin(mSkinnedModelInst->FinalTransforms),
  601.         std::end(mSkinnedModelInst->FinalTransforms),
  602.         &skinnedConstants.BoneTransforms[0]);
  603.  
  604.     currSkinnedCB->CopyData(0, skinnedConstants);
  605. }
  606.  
  607. void SkinnedMeshApp::UpdateMaterialBuffer(const GameTimer& gt)
  608. {
  609.     auto currMaterialBuffer = mCurrFrameResource->MaterialBuffer.get();
  610.     for(auto& e : mMaterials)
  611.     {
  612.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  613.         // data changes, it needs to be updated for each FrameResource.
  614.         Material* mat = e.second.get();
  615.         if(mat->NumFramesDirty > 0)
  616.         {
  617.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  618.  
  619.             MaterialData matData;
  620.             matData.DiffuseAlbedo = mat->DiffuseAlbedo;
  621.             matData.FresnelR0 = mat->FresnelR0;
  622.             matData.Roughness = mat->Roughness;
  623.             XMStoreFloat4x4(&matData.MatTransform, XMMatrixTranspose(matTransform));
  624.             matData.DiffuseMapIndex = mat->DiffuseSrvHeapIndex;
  625.             matData.NormalMapIndex = mat->NormalSrvHeapIndex;
  626.  
  627.             currMaterialBuffer->CopyData(mat->MatCBIndex, matData);
  628.  
  629.             // Next FrameResource need to be updated too.
  630.             mat->NumFramesDirty--;
  631.         }
  632.     }
  633. }
  634.  
  635. void SkinnedMeshApp::UpdateShadowTransform(const GameTimer& gt)
  636. {
  637.     // Only the first "main" light casts a shadow.
  638.     XMVECTOR lightDir = XMLoadFloat3(&mRotatedLightDirections[0]);
  639.     XMVECTOR lightPos = -2.0f*mSceneBounds.Radius*lightDir;
  640.     XMVECTOR targetPos = XMLoadFloat3(&mSceneBounds.Center);
  641.     XMVECTOR lightUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  642.     XMMATRIX lightView = XMMatrixLookAtLH(lightPos, targetPos, lightUp);
  643.  
  644.     XMStoreFloat3(&mLightPosW, lightPos);
  645.  
  646.     // Transform bounding sphere to light space.
  647.     XMFLOAT3 sphereCenterLS;
  648.     XMStoreFloat3(&sphereCenterLS, XMVector3TransformCoord(targetPos, lightView));
  649.  
  650.     // Ortho frustum in light space encloses scene.
  651.     float l = sphereCenterLS.x - mSceneBounds.Radius;
  652.     float b = sphereCenterLS.y - mSceneBounds.Radius;
  653.     float n = sphereCenterLS.z - mSceneBounds.Radius;
  654.     float r = sphereCenterLS.x + mSceneBounds.Radius;
  655.     float t = sphereCenterLS.y + mSceneBounds.Radius;
  656.     float f = sphereCenterLS.z + mSceneBounds.Radius;
  657.  
  658.     mLightNearZ = n;
  659.     mLightFarZ = f;
  660.     XMMATRIX lightProj = XMMatrixOrthographicOffCenterLH(l, r, b, t, n, f);
  661.  
  662.     // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
  663.     XMMATRIX T(
  664.         0.5f, 0.0f, 0.0f, 0.0f,
  665.         0.0f, -0.5f, 0.0f, 0.0f,
  666.         0.0f, 0.0f, 1.0f, 0.0f,
  667.         0.5f, 0.5f, 0.0f, 1.0f);
  668.  
  669.     XMMATRIX S = lightView*lightProj*T;
  670.     XMStoreFloat4x4(&mLightView, lightView);
  671.     XMStoreFloat4x4(&mLightProj, lightProj);
  672.     XMStoreFloat4x4(&mShadowTransform, S);
  673. }
  674.  
  675. void SkinnedMeshApp::UpdateMainPassCB(const GameTimer& gt)
  676. {
  677.     XMMATRIX view = mCamera.GetView();
  678.     XMMATRIX proj = mCamera.GetProj();
  679.  
  680.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  681.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  682.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  683.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  684.  
  685.     // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
  686.     XMMATRIX T(
  687.         0.5f, 0.0f, 0.0f, 0.0f,
  688.         0.0f, -0.5f, 0.0f, 0.0f,
  689.         0.0f, 0.0f, 1.0f, 0.0f,
  690.         0.5f, 0.5f, 0.0f, 1.0f);
  691.  
  692.     XMMATRIX viewProjTex = XMMatrixMultiply(viewProj, T);
  693.     XMMATRIX shadowTransform = XMLoadFloat4x4(&mShadowTransform);
  694.  
  695.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  696.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  697.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  698.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  699.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  700.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  701.     XMStoreFloat4x4(&mMainPassCB.ViewProjTex, XMMatrixTranspose(viewProjTex));
  702.     XMStoreFloat4x4(&mMainPassCB.ShadowTransform, XMMatrixTranspose(shadowTransform));
  703.     mMainPassCB.EyePosW = mCamera.GetPosition3f();
  704.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  705.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  706.     mMainPassCB.NearZ = 1.0f;
  707.     mMainPassCB.FarZ = 1000.0f;
  708.     mMainPassCB.TotalTime = gt.TotalTime();
  709.     mMainPassCB.DeltaTime = gt.DeltaTime();
  710.     mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
  711.     mMainPassCB.Lights[0].Direction = mRotatedLightDirections[0];
  712.     mMainPassCB.Lights[0].Strength = { 0.9f, 0.9f, 0.7f };
  713.     mMainPassCB.Lights[1].Direction = mRotatedLightDirections[1];
  714.     mMainPassCB.Lights[1].Strength = { 0.4f, 0.4f, 0.4f };
  715.     mMainPassCB.Lights[2].Direction = mRotatedLightDirections[2];
  716.     mMainPassCB.Lights[2].Strength = { 0.2f, 0.2f, 0.2f };
  717.  
  718.     auto currPassCB = mCurrFrameResource->PassCB.get();
  719.     currPassCB->CopyData(0, mMainPassCB);
  720. }
  721.  
  722. void SkinnedMeshApp::UpdateShadowPassCB(const GameTimer& gt)
  723. {
  724.     XMMATRIX view = XMLoadFloat4x4(&mLightView);
  725.     XMMATRIX proj = XMLoadFloat4x4(&mLightProj);
  726.  
  727.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  728.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  729.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  730.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  731.  
  732.     UINT w = mShadowMap->Width();
  733.     UINT h = mShadowMap->Height();
  734.  
  735.     XMStoreFloat4x4(&mShadowPassCB.View, XMMatrixTranspose(view));
  736.     XMStoreFloat4x4(&mShadowPassCB.InvView, XMMatrixTranspose(invView));
  737.     XMStoreFloat4x4(&mShadowPassCB.Proj, XMMatrixTranspose(proj));
  738.     XMStoreFloat4x4(&mShadowPassCB.InvProj, XMMatrixTranspose(invProj));
  739.     XMStoreFloat4x4(&mShadowPassCB.ViewProj, XMMatrixTranspose(viewProj));
  740.     XMStoreFloat4x4(&mShadowPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  741.     mShadowPassCB.EyePosW = mLightPosW;
  742.     mShadowPassCB.RenderTargetSize = XMFLOAT2((float)w, (float)h);
  743.     mShadowPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / w, 1.0f / h);
  744.     mShadowPassCB.NearZ = mLightNearZ;
  745.     mShadowPassCB.FarZ = mLightFarZ;
  746.  
  747.     auto currPassCB = mCurrFrameResource->PassCB.get();
  748.     currPassCB->CopyData(1, mShadowPassCB);
  749. }
  750.  
  751. void SkinnedMeshApp::UpdateSsaoCB(const GameTimer& gt)
  752. {
  753.     SsaoConstants ssaoCB;
  754.  
  755.     XMMATRIX P = mCamera.GetProj();
  756.  
  757.     // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
  758.     XMMATRIX T(
  759.         0.5f, 0.0f, 0.0f, 0.0f,
  760.         0.0f, -0.5f, 0.0f, 0.0f,
  761.         0.0f, 0.0f, 1.0f, 0.0f,
  762.         0.5f, 0.5f, 0.0f, 1.0f);
  763.  
  764.     ssaoCB.Proj    = mMainPassCB.Proj;
  765.     ssaoCB.InvProj = mMainPassCB.InvProj;
  766.     XMStoreFloat4x4(&ssaoCB.ProjTex, XMMatrixTranspose(P*T));
  767.  
  768.     mSsao->GetOffsetVectors(ssaoCB.OffsetVectors);
  769.  
  770.     auto blurWeights = mSsao->CalcGaussWeights(2.5f);
  771.     ssaoCB.BlurWeights[0] = XMFLOAT4(&blurWeights[0]);
  772.     ssaoCB.BlurWeights[1] = XMFLOAT4(&blurWeights[4]);
  773.     ssaoCB.BlurWeights[2] = XMFLOAT4(&blurWeights[8]);
  774.  
  775.     ssaoCB.InvRenderTargetSize = XMFLOAT2(1.0f / mSsao->SsaoMapWidth(), 1.0f / mSsao->SsaoMapHeight());
  776.  
  777.     // Coordinates given in view space.
  778.     ssaoCB.OcclusionRadius = 0.5f;
  779.     ssaoCB.OcclusionFadeStart = 0.2f;
  780.     ssaoCB.OcclusionFadeEnd = 2.0f;
  781.     ssaoCB.SurfaceEpsilon = 0.05f;
  782.  
  783.     auto currSsaoCB = mCurrFrameResource->SsaoCB.get();
  784.     currSsaoCB->CopyData(0, ssaoCB);
  785. }
  786.  
  787. void SkinnedMeshApp::LoadTextures()
  788. {
  789.     std::vector<std::string> texNames = 
  790.     {
  791.         "bricksDiffuseMap",
  792.         "bricksNormalMap",
  793.         "tileDiffuseMap",
  794.         "tileNormalMap",
  795.         "defaultDiffuseMap",
  796.         "defaultNormalMap",
  797.         "skyCubeMap"
  798.     };
  799.     
  800.     std::vector<std::wstring> texFilenames = 
  801.     {
  802.         L"../../Textures/bricks2.dds",
  803.         L"../../Textures/bricks2_nmap.dds",
  804.         L"../../Textures/tile.dds",
  805.         L"../../Textures/tile_nmap.dds",
  806.         L"../../Textures/white1x1.dds",
  807.         L"../../Textures/default_nmap.dds",
  808.         L"../../Textures/desertcube1024.dds"
  809.     };
  810.  
  811.     // Add skinned model textures to list so we can reference by name later.
  812.     for(UINT i = 0; i < mSkinnedMats.size(); ++i)
  813.     {
  814.         std::string diffuseName = mSkinnedMats[i].DiffuseMapName;
  815.         std::string normalName = mSkinnedMats[i].NormalMapName;
  816.  
  817.         std::wstring diffuseFilename = L"../../Textures/" + AnsiToWString(diffuseName);
  818.         std::wstring normalFilename = L"../../Textures/" + AnsiToWString(normalName);
  819.  
  820.         // strip off extension
  821.         diffuseName = diffuseName.substr(0, diffuseName.find_last_of("."));
  822.         normalName = normalName.substr(0, normalName.find_last_of("."));
  823.  
  824.         mSkinnedTextureNames.push_back(diffuseName);
  825.         texNames.push_back(diffuseName);
  826.         texFilenames.push_back(diffuseFilename);
  827.  
  828.         mSkinnedTextureNames.push_back(normalName);
  829.         texNames.push_back(normalName);
  830.         texFilenames.push_back(normalFilename);
  831.     }
  832.     
  833.     for(int i = 0; i < (int)texNames.size(); ++i)
  834.     {
  835.         // Don't create duplicates.
  836.         if(mTextures.find(texNames[i]) == std::end(mTextures))
  837.         {
  838.             auto texMap = std::make_unique<Texture>();
  839.             texMap->Name = texNames[i];
  840.             texMap->Filename = texFilenames[i];
  841.             ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  842.                 mCommandList.Get(), texMap->Filename.c_str(),
  843.                 texMap->Resource, texMap->UploadHeap));
  844.  
  845.             mTextures[texMap->Name] = std::move(texMap);
  846.         }
  847.     }        
  848. }
  849.  
  850. void SkinnedMeshApp::BuildRootSignature()
  851. {
  852.     CD3DX12_DESCRIPTOR_RANGE texTable0;
  853.     texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3, 0, 0);
  854.  
  855.     CD3DX12_DESCRIPTOR_RANGE texTable1;
  856.     texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 48, 3, 0);
  857.  
  858.     // Root parameter can be a table, root descriptor or root constants.
  859.     CD3DX12_ROOT_PARAMETER slotRootParameter[6];
  860.  
  861.     // Perfomance TIP: Order from most frequent to least frequent.
  862.     slotRootParameter[0].InitAsConstantBufferView(0);
  863.     slotRootParameter[1].InitAsConstantBufferView(1);
  864.     slotRootParameter[2].InitAsConstantBufferView(2);
  865.     slotRootParameter[3].InitAsShaderResourceView(0, 1);
  866.     slotRootParameter[4].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
  867.     slotRootParameter[5].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
  868.  
  869.     auto staticSamplers = GetStaticSamplers();
  870.  
  871.     // A root signature is an array of root parameters.
  872.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(6, slotRootParameter,
  873.         (UINT)staticSamplers.size(), staticSamplers.data(),
  874.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  875.  
  876.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  877.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  878.     ComPtr<ID3DBlob> errorBlob = nullptr;
  879.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  880.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  881.  
  882.     if(errorBlob != nullptr)
  883.     {
  884.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  885.     }
  886.     ThrowIfFailed(hr);
  887.  
  888.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  889.         0,
  890.         serializedRootSig->GetBufferPointer(),
  891.         serializedRootSig->GetBufferSize(),
  892.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  893. }
  894.  
  895. void SkinnedMeshApp::BuildSsaoRootSignature()
  896. {
  897.     CD3DX12_DESCRIPTOR_RANGE texTable0;
  898.     texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0, 0);
  899.  
  900.     CD3DX12_DESCRIPTOR_RANGE texTable1;
  901.     texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2, 0);
  902.  
  903.     // Root parameter can be a table, root descriptor or root constants.
  904.     CD3DX12_ROOT_PARAMETER slotRootParameter[4];
  905.  
  906.     // Perfomance TIP: Order from most frequent to least frequent.
  907.     slotRootParameter[0].InitAsConstantBufferView(0);
  908.     slotRootParameter[1].InitAsConstants(1, 1);
  909.     slotRootParameter[2].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
  910.     slotRootParameter[3].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
  911.  
  912.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  913.         0, // shaderRegister
  914.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  915.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  916.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  917.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  918.  
  919.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  920.         1, // shaderRegister
  921.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  922.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  923.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  924.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  925.  
  926.     const CD3DX12_STATIC_SAMPLER_DESC depthMapSam(
  927.         2, // shaderRegister
  928.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  929.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressU
  930.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressV
  931.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressW
  932.         0.0f,
  933.         0,
  934.         D3D12_COMPARISON_FUNC_LESS_EQUAL,
  935.         D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE); 
  936.  
  937.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  938.         3, // shaderRegister
  939.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  940.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  941.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  942.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  943.  
  944.     std::array<CD3DX12_STATIC_SAMPLER_DESC, 4> staticSamplers =
  945.     {
  946.         pointClamp, linearClamp, depthMapSam, linearWrap
  947.     };
  948.  
  949.     // A root signature is an array of root parameters.
  950.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
  951.         (UINT)staticSamplers.size(), staticSamplers.data(),
  952.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  953.  
  954.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  955.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  956.     ComPtr<ID3DBlob> errorBlob = nullptr;
  957.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  958.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  959.  
  960.     if(errorBlob != nullptr)
  961.     {
  962.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  963.     }
  964.     ThrowIfFailed(hr);
  965.  
  966.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  967.         0,
  968.         serializedRootSig->GetBufferPointer(),
  969.         serializedRootSig->GetBufferSize(),
  970.         IID_PPV_ARGS(mSsaoRootSignature.GetAddressOf())));
  971. }
  972.  
  973. void SkinnedMeshApp::BuildDescriptorHeaps()
  974. {
  975.     //
  976.     // Create the SRV heap.
  977.     //
  978.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  979.     srvHeapDesc.NumDescriptors = 64;
  980.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  981.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  982.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
  983.  
  984.     //
  985.     // Fill out the heap with actual descriptors.
  986.     //
  987.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  988.  
  989.     std::vector<ComPtr<ID3D12Resource>> tex2DList = 
  990.     {
  991.         mTextures["bricksDiffuseMap"]->Resource,
  992.         mTextures["bricksNormalMap"]->Resource,
  993.         mTextures["tileDiffuseMap"]->Resource,
  994.         mTextures["tileNormalMap"]->Resource,
  995.         mTextures["defaultDiffuseMap"]->Resource,
  996.         mTextures["defaultNormalMap"]->Resource
  997.     };
  998.  
  999.     mSkinnedSrvHeapStart = (UINT)tex2DList.size();
  1000.  
  1001.     for(UINT i = 0; i < (UINT)mSkinnedTextureNames.size(); ++i)
  1002.     {
  1003.         auto texResource = mTextures[mSkinnedTextureNames[i]]->Resource;
  1004.         assert(texResource != nullptr);
  1005.         tex2DList.push_back(texResource);
  1006.     }
  1007.     
  1008.  
  1009.     auto skyCubeMap = mTextures["skyCubeMap"]->Resource;
  1010.  
  1011.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  1012.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  1013.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  1014.     srvDesc.Texture2D.MostDetailedMip = 0;
  1015.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  1016.     
  1017.     for(UINT i = 0; i < (UINT)tex2DList.size(); ++i)
  1018.     {
  1019.         srvDesc.Format = tex2DList[i]->GetDesc().Format;
  1020.         srvDesc.Texture2D.MipLevels = tex2DList[i]->GetDesc().MipLevels;
  1021.         md3dDevice->CreateShaderResourceView(tex2DList[i].Get(), &srvDesc, hDescriptor);
  1022.  
  1023.         // next descriptor
  1024.         hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  1025.     }
  1026.     
  1027.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
  1028.     srvDesc.TextureCube.MostDetailedMip = 0;
  1029.     srvDesc.TextureCube.MipLevels = skyCubeMap->GetDesc().MipLevels;
  1030.     srvDesc.TextureCube.ResourceMinLODClamp = 0.0f;
  1031.     srvDesc.Format = skyCubeMap->GetDesc().Format;
  1032.     md3dDevice->CreateShaderResourceView(skyCubeMap.Get(), &srvDesc, hDescriptor);
  1033.     
  1034.     mSkyTexHeapIndex = (UINT)tex2DList.size();
  1035.     mShadowMapHeapIndex = mSkyTexHeapIndex + 1;
  1036.     mSsaoHeapIndexStart = mShadowMapHeapIndex + 1;
  1037.     mSsaoAmbientMapIndex = mSsaoHeapIndexStart + 3;
  1038.     mNullCubeSrvIndex = mSsaoHeapIndexStart + 5;
  1039.     mNullTexSrvIndex1 = mNullCubeSrvIndex + 1;
  1040.     mNullTexSrvIndex2 = mNullTexSrvIndex1 + 1;
  1041.  
  1042.     auto nullSrv = GetCpuSrv(mNullCubeSrvIndex);
  1043.     mNullSrv = GetGpuSrv(mNullCubeSrvIndex);
  1044.  
  1045.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  1046.     nullSrv.Offset(1, mCbvSrvUavDescriptorSize);
  1047.  
  1048.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  1049.     srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  1050.     srvDesc.Texture2D.MostDetailedMip = 0;
  1051.     srvDesc.Texture2D.MipLevels = 1;
  1052.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  1053.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  1054.  
  1055.     nullSrv.Offset(1, mCbvSrvUavDescriptorSize);
  1056.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  1057.  
  1058.     mShadowMap->BuildDescriptors(
  1059.         GetCpuSrv(mShadowMapHeapIndex),
  1060.         GetGpuSrv(mShadowMapHeapIndex),
  1061.         GetDsv(1));
  1062.  
  1063.     mSsao->BuildDescriptors(
  1064.         mDepthStencilBuffer.Get(),
  1065.         GetCpuSrv(mSsaoHeapIndexStart),
  1066.         GetGpuSrv(mSsaoHeapIndexStart),
  1067.         GetRtv(SwapChainBufferCount),
  1068.         mCbvSrvUavDescriptorSize,
  1069.         mRtvDescriptorSize);
  1070. }
  1071.  
  1072. void SkinnedMeshApp::BuildShadersAndInputLayout()
  1073. {
  1074.     const D3D_SHADER_MACRO alphaTestDefines[] =
  1075.     {
  1076.         "ALPHA_TEST", "1",
  1077.         NULL, NULL
  1078.     };
  1079.  
  1080.     const D3D_SHADER_MACRO skinnedDefines[] =
  1081.     {
  1082.         "SKINNED", "1",
  1083.         NULL, NULL
  1084.     };
  1085.  
  1086.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_1");
  1087.     mShaders["skinnedVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", skinnedDefines, "VS", "vs_5_1");
  1088.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "PS", "ps_5_1");
  1089.  
  1090.     mShaders["shadowVS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", nullptr, "VS", "vs_5_1");
  1091.     mShaders["skinnedShadowVS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", skinnedDefines, "VS", "vs_5_1");
  1092.     mShaders["shadowOpaquePS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", nullptr, "PS", "ps_5_1");
  1093.     mShaders["shadowAlphaTestedPS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", alphaTestDefines, "PS", "ps_5_1");
  1094.     
  1095.     mShaders["debugVS"] = d3dUtil::CompileShader(L"Shaders\\ShadowDebug.hlsl", nullptr, "VS", "vs_5_1");
  1096.     mShaders["debugPS"] = d3dUtil::CompileShader(L"Shaders\\ShadowDebug.hlsl", nullptr, "PS", "ps_5_1");
  1097.  
  1098.     mShaders["drawNormalsVS"] = d3dUtil::CompileShader(L"Shaders\\DrawNormals.hlsl", nullptr, "VS", "vs_5_1");
  1099.     mShaders["skinnedDrawNormalsVS"] = d3dUtil::CompileShader(L"Shaders\\DrawNormals.hlsl", skinnedDefines, "VS", "vs_5_1");
  1100.     mShaders["drawNormalsPS"] = d3dUtil::CompileShader(L"Shaders\\DrawNormals.hlsl", nullptr, "PS", "ps_5_1");
  1101.  
  1102.     mShaders["ssaoVS"] = d3dUtil::CompileShader(L"Shaders\\Ssao.hlsl", nullptr, "VS", "vs_5_1");
  1103.     mShaders["ssaoPS"] = d3dUtil::CompileShader(L"Shaders\\Ssao.hlsl", nullptr, "PS", "ps_5_1");
  1104.  
  1105.     mShaders["ssaoBlurVS"] = d3dUtil::CompileShader(L"Shaders\\SsaoBlur.hlsl", nullptr, "VS", "vs_5_1");
  1106.     mShaders["ssaoBlurPS"] = d3dUtil::CompileShader(L"Shaders\\SsaoBlur.hlsl", nullptr, "PS", "ps_5_1");
  1107.  
  1108.     mShaders["skyVS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "VS", "vs_5_1");
  1109.     mShaders["skyPS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "PS", "ps_5_1");
  1110.  
  1111.     mInputLayout =
  1112.     {
  1113.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1114.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1115.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1116.         { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1117.     };
  1118.  
  1119.     mSkinnedInputLayout =
  1120.     {
  1121.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1122.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1123.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1124.         { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1125.         { "WEIGHTS", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 44, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  1126.         { "BONEINDICES", 0, DXGI_FORMAT_R8G8B8A8_UINT, 0, 56, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
  1127.     };
  1128. }
  1129.  
  1130. void SkinnedMeshApp::BuildShapeGeometry()
  1131. {
  1132.     GeometryGenerator geoGen;
  1133.     GeometryGenerator::MeshData box = geoGen.CreateBox(1.0f, 1.0f, 1.0f, 3);
  1134.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
  1135.     GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
  1136.     GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
  1137.     GeometryGenerator::MeshData quad = geoGen.CreateQuad(0.0f, 0.0f, 1.0f, 1.0f, 0.0f);
  1138.     
  1139.     //
  1140.     // We are concatenating all the geometry into one big vertex/index buffer.  So
  1141.     // define the regions in the buffer each submesh covers.
  1142.     //
  1143.  
  1144.     // Cache the vertex offsets to each object in the concatenated vertex buffer.
  1145.     UINT boxVertexOffset = 0;
  1146.     UINT gridVertexOffset = (UINT)box.Vertices.size();
  1147.     UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
  1148.     UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
  1149.     UINT quadVertexOffset = cylinderVertexOffset + (UINT)cylinder.Vertices.size();
  1150.  
  1151.     // Cache the starting index for each object in the concatenated index buffer.
  1152.     UINT boxIndexOffset = 0;
  1153.     UINT gridIndexOffset = (UINT)box.Indices32.size();
  1154.     UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
  1155.     UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
  1156.     UINT quadIndexOffset = cylinderIndexOffset + (UINT)cylinder.Indices32.size();
  1157.  
  1158.     SubmeshGeometry boxSubmesh;
  1159.     boxSubmesh.IndexCount = (UINT)box.Indices32.size();
  1160.     boxSubmesh.StartIndexLocation = boxIndexOffset;
  1161.     boxSubmesh.BaseVertexLocation = boxVertexOffset;
  1162.  
  1163.     SubmeshGeometry gridSubmesh;
  1164.     gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
  1165.     gridSubmesh.StartIndexLocation = gridIndexOffset;
  1166.     gridSubmesh.BaseVertexLocation = gridVertexOffset;
  1167.  
  1168.     SubmeshGeometry sphereSubmesh;
  1169.     sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
  1170.     sphereSubmesh.StartIndexLocation = sphereIndexOffset;
  1171.     sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
  1172.  
  1173.     SubmeshGeometry cylinderSubmesh;
  1174.     cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
  1175.     cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
  1176.     cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
  1177.  
  1178.     SubmeshGeometry quadSubmesh;
  1179.     quadSubmesh.IndexCount = (UINT)quad.Indices32.size();
  1180.     quadSubmesh.StartIndexLocation = quadIndexOffset;
  1181.     quadSubmesh.BaseVertexLocation = quadVertexOffset;
  1182.  
  1183.     //
  1184.     // Extract the vertex elements we are interested in and pack the
  1185.     // vertices of all the meshes into one vertex buffer.
  1186.     //
  1187.  
  1188.     auto totalVertexCount =
  1189.         box.Vertices.size() +
  1190.         grid.Vertices.size() +
  1191.         sphere.Vertices.size() +
  1192.         cylinder.Vertices.size() + 
  1193.         quad.Vertices.size();
  1194.  
  1195.     std::vector<Vertex> vertices(totalVertexCount);
  1196.  
  1197.     UINT k = 0;
  1198.     for(size_t i = 0; i < box.Vertices.size(); ++i, ++k)
  1199.     {
  1200.         vertices[k].Pos = box.Vertices[i].Position;
  1201.         vertices[k].Normal = box.Vertices[i].Normal;
  1202.         vertices[k].TexC = box.Vertices[i].TexC;
  1203.         vertices[k].TangentU = box.Vertices[i].TangentU;
  1204.     }
  1205.  
  1206.     for(size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
  1207.     {
  1208.         vertices[k].Pos = grid.Vertices[i].Position;
  1209.         vertices[k].Normal = grid.Vertices[i].Normal;
  1210.         vertices[k].TexC = grid.Vertices[i].TexC;
  1211.         vertices[k].TangentU = grid.Vertices[i].TangentU;
  1212.     }
  1213.  
  1214.     for(size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
  1215.     {
  1216.         vertices[k].Pos = sphere.Vertices[i].Position;
  1217.         vertices[k].Normal = sphere.Vertices[i].Normal;
  1218.         vertices[k].TexC = sphere.Vertices[i].TexC;
  1219.         vertices[k].TangentU = sphere.Vertices[i].TangentU;
  1220.     }
  1221.  
  1222.     for(size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
  1223.     {
  1224.         vertices[k].Pos = cylinder.Vertices[i].Position;
  1225.         vertices[k].Normal = cylinder.Vertices[i].Normal;
  1226.         vertices[k].TexC = cylinder.Vertices[i].TexC;
  1227.         vertices[k].TangentU = cylinder.Vertices[i].TangentU;
  1228.     }
  1229.  
  1230.     for(int i = 0; i < quad.Vertices.size(); ++i, ++k)
  1231.     {
  1232.         vertices[k].Pos = quad.Vertices[i].Position;
  1233.         vertices[k].Normal = quad.Vertices[i].Normal;
  1234.         vertices[k].TexC = quad.Vertices[i].TexC;
  1235.         vertices[k].TangentU = quad.Vertices[i].TangentU;
  1236.     }
  1237.  
  1238.     std::vector<std::uint16_t> indices;
  1239.     indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
  1240.     indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
  1241.     indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
  1242.     indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
  1243.     indices.insert(indices.end(), std::begin(quad.GetIndices16()), std::end(quad.GetIndices16()));
  1244.  
  1245.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  1246.     const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
  1247.  
  1248.     auto geo = std::make_unique<MeshGeometry>();
  1249.     geo->Name = "shapeGeo";
  1250.  
  1251.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  1252.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  1253.  
  1254.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  1255.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  1256.  
  1257.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1258.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  1259.  
  1260.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1261.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  1262.  
  1263.     geo->VertexByteStride = sizeof(Vertex);
  1264.     geo->VertexBufferByteSize = vbByteSize;
  1265.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  1266.     geo->IndexBufferByteSize = ibByteSize;
  1267.  
  1268.     geo->DrawArgs["box"] = boxSubmesh;
  1269.     geo->DrawArgs["grid"] = gridSubmesh;
  1270.     geo->DrawArgs["sphere"] = sphereSubmesh;
  1271.     geo->DrawArgs["cylinder"] = cylinderSubmesh;
  1272.     geo->DrawArgs["quad"] = quadSubmesh;
  1273.  
  1274.     mGeometries[geo->Name] = std::move(geo);
  1275. }
  1276.  
  1277. void SkinnedMeshApp::LoadSkinnedModel()
  1278. {
  1279.     std::vector<M3DLoader::SkinnedVertex> vertices;
  1280.     std::vector<std::uint16_t> indices;    
  1281.  
  1282.     M3DLoader m3dLoader;
  1283.     m3dLoader.LoadM3d(mSkinnedModelFilename, vertices, indices, 
  1284.         mSkinnedSubsets, mSkinnedMats, mSkinnedInfo);
  1285.  
  1286.     mSkinnedModelInst = std::make_unique<SkinnedModelInstance>();
  1287.     mSkinnedModelInst->SkinnedInfo = &mSkinnedInfo;
  1288.     mSkinnedModelInst->FinalTransforms.resize(mSkinnedInfo.BoneCount());
  1289.     mSkinnedModelInst->ClipName = "Take1";
  1290.     mSkinnedModelInst->TimePos = 0.0f;
  1291.  
  1292.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(SkinnedVertex);
  1293.     const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
  1294.  
  1295.     auto geo = std::make_unique<MeshGeometry>();
  1296.     geo->Name = mSkinnedModelFilename;
  1297.  
  1298.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  1299.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  1300.  
  1301.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  1302.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  1303.  
  1304.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1305.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  1306.  
  1307.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1308.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  1309.  
  1310.     geo->VertexByteStride = sizeof(SkinnedVertex);
  1311.     geo->VertexBufferByteSize = vbByteSize;
  1312.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  1313.     geo->IndexBufferByteSize = ibByteSize;
  1314.  
  1315.     for(UINT i = 0; i < (UINT)mSkinnedSubsets.size(); ++i)
  1316.     {
  1317.         SubmeshGeometry submesh;
  1318.         std::string name = "sm_" + std::to_string(i);
  1319.         
  1320.         submesh.IndexCount = (UINT)mSkinnedSubsets[i].FaceCount * 3;
  1321.         submesh.StartIndexLocation = mSkinnedSubsets[i].FaceStart * 3;
  1322.         submesh.BaseVertexLocation = 0;
  1323.  
  1324.         geo->DrawArgs[name] = submesh;
  1325.     }
  1326.  
  1327.     mGeometries[geo->Name] = std::move(geo);
  1328. }
  1329.  
  1330. void SkinnedMeshApp::BuildPSOs()
  1331. {
  1332.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
  1333.  
  1334.     //
  1335.     // PSO for opaque objects.
  1336.     //
  1337.     ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  1338.     opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  1339.     opaquePsoDesc.pRootSignature = mRootSignature.Get();
  1340.     opaquePsoDesc.VS = 
  1341.     { 
  1342.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  1343.         mShaders["standardVS"]->GetBufferSize()
  1344.     };
  1345.     opaquePsoDesc.PS = 
  1346.     { 
  1347.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  1348.         mShaders["opaquePS"]->GetBufferSize()
  1349.     };
  1350.     opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  1351.     opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  1352.     opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  1353.     opaquePsoDesc.SampleMask = UINT_MAX;
  1354.     opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  1355.     opaquePsoDesc.NumRenderTargets = 1;
  1356.     opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
  1357.     opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  1358.     opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  1359.     opaquePsoDesc.DSVFormat = mDepthStencilFormat;
  1360.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  1361.  
  1362.     //
  1363.     // PSO for skinned pass.
  1364.     //
  1365.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skinnedOpaquePsoDesc = opaquePsoDesc;
  1366.     skinnedOpaquePsoDesc.InputLayout = { mSkinnedInputLayout.data(), (UINT)mSkinnedInputLayout.size() };
  1367.     skinnedOpaquePsoDesc.VS =
  1368.     {
  1369.         reinterpret_cast<BYTE*>(mShaders["skinnedVS"]->GetBufferPointer()),
  1370.         mShaders["skinnedVS"]->GetBufferSize()
  1371.     };
  1372.     skinnedOpaquePsoDesc.PS =
  1373.     {
  1374.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  1375.         mShaders["opaquePS"]->GetBufferSize()
  1376.     };
  1377.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skinnedOpaquePsoDesc, IID_PPV_ARGS(&mPSOs["skinnedOpaque"])));
  1378.  
  1379.     //
  1380.     // PSO for shadow map pass.
  1381.     //
  1382.     D3D12_GRAPHICS_PIPELINE_STATE_DESC smapPsoDesc = opaquePsoDesc;
  1383.     smapPsoDesc.RasterizerState.DepthBias = 100000;
  1384.     smapPsoDesc.RasterizerState.DepthBiasClamp = 0.0f;
  1385.     smapPsoDesc.RasterizerState.SlopeScaledDepthBias = 1.0f;
  1386.     smapPsoDesc.pRootSignature = mRootSignature.Get();
  1387.     smapPsoDesc.VS =
  1388.     {
  1389.         reinterpret_cast<BYTE*>(mShaders["shadowVS"]->GetBufferPointer()),
  1390.         mShaders["shadowVS"]->GetBufferSize()
  1391.     };
  1392.     smapPsoDesc.PS =
  1393.     {
  1394.         reinterpret_cast<BYTE*>(mShaders["shadowOpaquePS"]->GetBufferPointer()),
  1395.         mShaders["shadowOpaquePS"]->GetBufferSize()
  1396.     };
  1397.     
  1398.     // Shadow map pass does not have a render target.
  1399.     smapPsoDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;
  1400.     smapPsoDesc.NumRenderTargets = 0;
  1401.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&smapPsoDesc, IID_PPV_ARGS(&mPSOs["shadow_opaque"])));
  1402.  
  1403.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skinnedSmapPsoDesc = smapPsoDesc;
  1404.     skinnedSmapPsoDesc.InputLayout = { mSkinnedInputLayout.data(), (UINT)mSkinnedInputLayout.size() };
  1405.     skinnedSmapPsoDesc.VS =
  1406.     {
  1407.         reinterpret_cast<BYTE*>(mShaders["skinnedShadowVS"]->GetBufferPointer()),
  1408.         mShaders["skinnedShadowVS"]->GetBufferSize()
  1409.     };
  1410.     skinnedSmapPsoDesc.PS =
  1411.     {
  1412.         reinterpret_cast<BYTE*>(mShaders["shadowOpaquePS"]->GetBufferPointer()),
  1413.         mShaders["shadowOpaquePS"]->GetBufferSize()
  1414.     };
  1415.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skinnedSmapPsoDesc, IID_PPV_ARGS(&mPSOs["skinnedShadow_opaque"])));
  1416.  
  1417.     //
  1418.     // PSO for debug layer.
  1419.     //
  1420.     D3D12_GRAPHICS_PIPELINE_STATE_DESC debugPsoDesc = opaquePsoDesc;
  1421.     debugPsoDesc.pRootSignature = mRootSignature.Get();
  1422.     debugPsoDesc.VS =
  1423.     {
  1424.         reinterpret_cast<BYTE*>(mShaders["debugVS"]->GetBufferPointer()),
  1425.         mShaders["debugVS"]->GetBufferSize()
  1426.     };
  1427.     debugPsoDesc.PS =
  1428.     {
  1429.         reinterpret_cast<BYTE*>(mShaders["debugPS"]->GetBufferPointer()),
  1430.         mShaders["debugPS"]->GetBufferSize()
  1431.     };
  1432.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&debugPsoDesc, IID_PPV_ARGS(&mPSOs["debug"])));
  1433.  
  1434.     //
  1435.     // PSO for drawing normals.
  1436.     //
  1437.     D3D12_GRAPHICS_PIPELINE_STATE_DESC drawNormalsPsoDesc = opaquePsoDesc;
  1438.     drawNormalsPsoDesc.VS =
  1439.     {
  1440.         reinterpret_cast<BYTE*>(mShaders["drawNormalsVS"]->GetBufferPointer()),
  1441.         mShaders["drawNormalsVS"]->GetBufferSize()
  1442.     };
  1443.     drawNormalsPsoDesc.PS =
  1444.     {
  1445.         reinterpret_cast<BYTE*>(mShaders["drawNormalsPS"]->GetBufferPointer()),
  1446.         mShaders["drawNormalsPS"]->GetBufferSize()
  1447.     };
  1448.     drawNormalsPsoDesc.RTVFormats[0] = Ssao::NormalMapFormat;
  1449.     drawNormalsPsoDesc.SampleDesc.Count = 1;
  1450.     drawNormalsPsoDesc.SampleDesc.Quality = 0;
  1451.     drawNormalsPsoDesc.DSVFormat = mDepthStencilFormat;
  1452.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&drawNormalsPsoDesc, IID_PPV_ARGS(&mPSOs["drawNormals"])));
  1453.  
  1454.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skinnedDrawNormalsPsoDesc = drawNormalsPsoDesc;
  1455.     skinnedDrawNormalsPsoDesc.InputLayout = { mSkinnedInputLayout.data(), (UINT)mSkinnedInputLayout.size() };
  1456.     skinnedDrawNormalsPsoDesc.VS =
  1457.     {
  1458.         reinterpret_cast<BYTE*>(mShaders["skinnedDrawNormalsVS"]->GetBufferPointer()),
  1459.         mShaders["skinnedDrawNormalsVS"]->GetBufferSize()
  1460.     };
  1461.     skinnedDrawNormalsPsoDesc.PS =
  1462.     {
  1463.         reinterpret_cast<BYTE*>(mShaders["drawNormalsPS"]->GetBufferPointer()),
  1464.         mShaders["drawNormalsPS"]->GetBufferSize()
  1465.     };
  1466.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skinnedDrawNormalsPsoDesc, IID_PPV_ARGS(&mPSOs["skinnedDrawNormals"])));
  1467.  
  1468.     //
  1469.     // PSO for SSAO.
  1470.     //
  1471.     D3D12_GRAPHICS_PIPELINE_STATE_DESC ssaoPsoDesc = opaquePsoDesc;
  1472.     ssaoPsoDesc.InputLayout = { nullptr, 0 };
  1473.     ssaoPsoDesc.pRootSignature = mSsaoRootSignature.Get();
  1474.     ssaoPsoDesc.VS =
  1475.     {
  1476.         reinterpret_cast<BYTE*>(mShaders["ssaoVS"]->GetBufferPointer()),
  1477.         mShaders["ssaoVS"]->GetBufferSize()
  1478.     };
  1479.     ssaoPsoDesc.PS =
  1480.     {
  1481.         reinterpret_cast<BYTE*>(mShaders["ssaoPS"]->GetBufferPointer()),
  1482.         mShaders["ssaoPS"]->GetBufferSize()
  1483.     };
  1484.  
  1485.     // SSAO effect does not need the depth buffer.
  1486.     ssaoPsoDesc.DepthStencilState.DepthEnable = false;
  1487.     ssaoPsoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
  1488.     ssaoPsoDesc.RTVFormats[0] = Ssao::AmbientMapFormat;
  1489.     ssaoPsoDesc.SampleDesc.Count = 1;
  1490.     ssaoPsoDesc.SampleDesc.Quality = 0;
  1491.     ssaoPsoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
  1492.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&ssaoPsoDesc, IID_PPV_ARGS(&mPSOs["ssao"])));
  1493.  
  1494.     //
  1495.     // PSO for SSAO blur.
  1496.     //
  1497.     D3D12_GRAPHICS_PIPELINE_STATE_DESC ssaoBlurPsoDesc = ssaoPsoDesc;
  1498.     ssaoBlurPsoDesc.VS =
  1499.     {
  1500.         reinterpret_cast<BYTE*>(mShaders["ssaoBlurVS"]->GetBufferPointer()),
  1501.         mShaders["ssaoBlurVS"]->GetBufferSize()
  1502.     };
  1503.     ssaoBlurPsoDesc.PS =
  1504.     {
  1505.         reinterpret_cast<BYTE*>(mShaders["ssaoBlurPS"]->GetBufferPointer()),
  1506.         mShaders["ssaoBlurPS"]->GetBufferSize()
  1507.     };
  1508.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&ssaoBlurPsoDesc, IID_PPV_ARGS(&mPSOs["ssaoBlur"])));
  1509.  
  1510.     //
  1511.     // PSO for sky.
  1512.     //
  1513.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skyPsoDesc = opaquePsoDesc;
  1514.  
  1515.     // The camera is inside the sky sphere, so just turn off culling.
  1516.     skyPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
  1517.  
  1518.     // Make sure the depth function is LESS_EQUAL and not just LESS.  
  1519.     // Otherwise, the normalized depth values at z = 1 (NDC) will 
  1520.     // fail the depth test if the depth buffer was cleared to 1.
  1521.     skyPsoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
  1522.     skyPsoDesc.pRootSignature = mRootSignature.Get();
  1523.     skyPsoDesc.VS =
  1524.     {
  1525.         reinterpret_cast<BYTE*>(mShaders["skyVS"]->GetBufferPointer()),
  1526.         mShaders["skyVS"]->GetBufferSize()
  1527.     };
  1528.     skyPsoDesc.PS =
  1529.     {
  1530.         reinterpret_cast<BYTE*>(mShaders["skyPS"]->GetBufferPointer()),
  1531.         mShaders["skyPS"]->GetBufferSize()
  1532.     };
  1533.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skyPsoDesc, IID_PPV_ARGS(&mPSOs["sky"])));
  1534.  
  1535. }
  1536.  
  1537. void SkinnedMeshApp::BuildFrameResources()
  1538. {
  1539.     for(int i = 0; i < gNumFrameResources; ++i)
  1540.     {
  1541.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  1542.             2, (UINT)mAllRitems.size(), 
  1543.             1,
  1544.             (UINT)mMaterials.size()));
  1545.     }
  1546. }
  1547.  
  1548. void SkinnedMeshApp::BuildMaterials()
  1549. {
  1550.     auto bricks0 = std::make_unique<Material>();
  1551.     bricks0->Name = "bricks0";
  1552.     bricks0->MatCBIndex = 0;
  1553.     bricks0->DiffuseSrvHeapIndex = 0;
  1554.     bricks0->NormalSrvHeapIndex = 1;
  1555.     bricks0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1556.     bricks0->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1557.     bricks0->Roughness = 0.3f;
  1558.  
  1559.     auto tile0 = std::make_unique<Material>();
  1560.     tile0->Name = "tile0";
  1561.     tile0->MatCBIndex = 1;
  1562.     tile0->DiffuseSrvHeapIndex = 2;
  1563.     tile0->NormalSrvHeapIndex = 3;
  1564.     tile0->DiffuseAlbedo = XMFLOAT4(0.9f, 0.9f, 0.9f, 1.0f);
  1565.     tile0->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  1566.     tile0->Roughness = 0.1f;
  1567.  
  1568.     auto mirror0 = std::make_unique<Material>();
  1569.     mirror0->Name = "mirror0";
  1570.     mirror0->MatCBIndex = 2;
  1571.     mirror0->DiffuseSrvHeapIndex = 4;
  1572.     mirror0->NormalSrvHeapIndex = 5;
  1573.     mirror0->DiffuseAlbedo = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
  1574.     mirror0->FresnelR0 = XMFLOAT3(0.98f, 0.97f, 0.95f);
  1575.     mirror0->Roughness = 0.1f;
  1576.  
  1577.     auto sky = std::make_unique<Material>();
  1578.     sky->Name = "sky";
  1579.     sky->MatCBIndex = 3;
  1580.     sky->DiffuseSrvHeapIndex = 6;
  1581.     sky->NormalSrvHeapIndex = 7;
  1582.     sky->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1583.     sky->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1584.     sky->Roughness = 1.0f;
  1585.  
  1586.     mMaterials["bricks0"] = std::move(bricks0);
  1587.     mMaterials["tile0"] = std::move(tile0);
  1588.     mMaterials["mirror0"] = std::move(mirror0);
  1589.     mMaterials["sky"] = std::move(sky);
  1590.  
  1591.     UINT matCBIndex = 4;
  1592.     UINT srvHeapIndex = mSkinnedSrvHeapStart;
  1593.     for(UINT i = 0; i < mSkinnedMats.size(); ++i)
  1594.     {
  1595.         auto mat = std::make_unique<Material>();
  1596.         mat->Name = mSkinnedMats[i].Name;
  1597.         mat->MatCBIndex = matCBIndex++;
  1598.         mat->DiffuseSrvHeapIndex = srvHeapIndex++;
  1599.         mat->NormalSrvHeapIndex = srvHeapIndex++;
  1600.         mat->DiffuseAlbedo = mSkinnedMats[i].DiffuseAlbedo;
  1601.         mat->FresnelR0 = mSkinnedMats[i].FresnelR0;
  1602.         mat->Roughness = mSkinnedMats[i].Roughness;
  1603.  
  1604.         mMaterials[mat->Name] = std::move(mat);
  1605.     }
  1606. }
  1607.  
  1608. void SkinnedMeshApp::BuildRenderItems()
  1609. {
  1610.     auto skyRitem = std::make_unique<RenderItem>();
  1611.     XMStoreFloat4x4(&skyRitem->World, XMMatrixScaling(5000.0f, 5000.0f, 5000.0f));
  1612.     skyRitem->TexTransform = MathHelper::Identity4x4();
  1613.     skyRitem->ObjCBIndex = 0;
  1614.     skyRitem->Mat = mMaterials["sky"].get();
  1615.     skyRitem->Geo = mGeometries["shapeGeo"].get();
  1616.     skyRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1617.     skyRitem->IndexCount = skyRitem->Geo->DrawArgs["sphere"].IndexCount;
  1618.     skyRitem->StartIndexLocation = skyRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1619.     skyRitem->BaseVertexLocation = skyRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1620.  
  1621.     mRitemLayer[(int)RenderLayer::Sky].push_back(skyRitem.get());
  1622.     mAllRitems.push_back(std::move(skyRitem));
  1623.     
  1624.     auto quadRitem = std::make_unique<RenderItem>();
  1625.     quadRitem->World = MathHelper::Identity4x4();
  1626.     quadRitem->TexTransform = MathHelper::Identity4x4();
  1627.     quadRitem->ObjCBIndex = 1;
  1628.     quadRitem->Mat = mMaterials["bricks0"].get();
  1629.     quadRitem->Geo = mGeometries["shapeGeo"].get();
  1630.     quadRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1631.     quadRitem->IndexCount = quadRitem->Geo->DrawArgs["quad"].IndexCount;
  1632.     quadRitem->StartIndexLocation = quadRitem->Geo->DrawArgs["quad"].StartIndexLocation;
  1633.     quadRitem->BaseVertexLocation = quadRitem->Geo->DrawArgs["quad"].BaseVertexLocation;
  1634.  
  1635.     mRitemLayer[(int)RenderLayer::Debug].push_back(quadRitem.get());
  1636.     mAllRitems.push_back(std::move(quadRitem));
  1637.     
  1638.     auto boxRitem = std::make_unique<RenderItem>();
  1639.     XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 1.0f, 2.0f)*XMMatrixTranslation(0.0f, 0.5f, 0.0f));
  1640.     XMStoreFloat4x4(&boxRitem->TexTransform, XMMatrixScaling(1.0f, 1.0f, 1.0f));
  1641.     boxRitem->ObjCBIndex = 2;
  1642.     boxRitem->Mat = mMaterials["bricks0"].get();
  1643.     boxRitem->Geo = mGeometries["shapeGeo"].get();
  1644.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1645.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  1646.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  1647.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  1648.  
  1649.     mRitemLayer[(int)RenderLayer::Opaque].push_back(boxRitem.get());
  1650.     mAllRitems.push_back(std::move(boxRitem));
  1651.  
  1652.     auto gridRitem = std::make_unique<RenderItem>();
  1653.     gridRitem->World = MathHelper::Identity4x4();
  1654.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(8.0f, 8.0f, 1.0f));
  1655.     gridRitem->ObjCBIndex = 3;
  1656.     gridRitem->Mat = mMaterials["tile0"].get();
  1657.     gridRitem->Geo = mGeometries["shapeGeo"].get();
  1658.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1659.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  1660.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  1661.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  1662.  
  1663.     mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
  1664.     mAllRitems.push_back(std::move(gridRitem));
  1665.  
  1666.     XMMATRIX brickTexTransform = XMMatrixScaling(1.5f, 2.0f, 1.0f);
  1667.     UINT objCBIndex = 4;
  1668.     for(int i = 0; i < 5; ++i)
  1669.     {
  1670.         auto leftCylRitem = std::make_unique<RenderItem>();
  1671.         auto rightCylRitem = std::make_unique<RenderItem>();
  1672.         auto leftSphereRitem = std::make_unique<RenderItem>();
  1673.         auto rightSphereRitem = std::make_unique<RenderItem>();
  1674.  
  1675.         XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i*5.0f);
  1676.         XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i*5.0f);
  1677.  
  1678.         XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i*5.0f);
  1679.         XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i*5.0f);
  1680.  
  1681.         XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
  1682.         XMStoreFloat4x4(&leftCylRitem->TexTransform, brickTexTransform);
  1683.         leftCylRitem->ObjCBIndex = objCBIndex++;
  1684.         leftCylRitem->Mat = mMaterials["bricks0"].get();
  1685.         leftCylRitem->Geo = mGeometries["shapeGeo"].get();
  1686.         leftCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1687.         leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1688.         leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1689.         leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1690.  
  1691.         XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
  1692.         XMStoreFloat4x4(&rightCylRitem->TexTransform, brickTexTransform);
  1693.         rightCylRitem->ObjCBIndex = objCBIndex++;
  1694.         rightCylRitem->Mat = mMaterials["bricks0"].get();
  1695.         rightCylRitem->Geo = mGeometries["shapeGeo"].get();
  1696.         rightCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1697.         rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1698.         rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1699.         rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1700.  
  1701.         XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
  1702.         leftSphereRitem->TexTransform = MathHelper::Identity4x4();
  1703.         leftSphereRitem->ObjCBIndex = objCBIndex++;
  1704.         leftSphereRitem->Mat = mMaterials["mirror0"].get();
  1705.         leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1706.         leftSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1707.         leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1708.         leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1709.         leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1710.  
  1711.         XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
  1712.         rightSphereRitem->TexTransform = MathHelper::Identity4x4();
  1713.         rightSphereRitem->ObjCBIndex = objCBIndex++;
  1714.         rightSphereRitem->Mat = mMaterials["mirror0"].get();
  1715.         rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1716.         rightSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1717.         rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1718.         rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1719.         rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1720.  
  1721.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftCylRitem.get());
  1722.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightCylRitem.get());
  1723.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftSphereRitem.get());
  1724.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightSphereRitem.get());
  1725.  
  1726.         mAllRitems.push_back(std::move(leftCylRitem));
  1727.         mAllRitems.push_back(std::move(rightCylRitem));
  1728.         mAllRitems.push_back(std::move(leftSphereRitem));
  1729.         mAllRitems.push_back(std::move(rightSphereRitem));
  1730.     }
  1731.  
  1732.     for(UINT i = 0; i < mSkinnedMats.size(); ++i)
  1733.     {
  1734.         std::string submeshName = "sm_" + std::to_string(i);
  1735.  
  1736.         auto ritem = std::make_unique<RenderItem>();
  1737.  
  1738.         // Reflect to change coordinate system from the RHS the data was exported out as.
  1739.         XMMATRIX modelScale = XMMatrixScaling(0.05f, 0.05f, -0.05f);
  1740.         XMMATRIX modelRot = XMMatrixRotationY(MathHelper::Pi);
  1741.         XMMATRIX modelOffset = XMMatrixTranslation(0.0f, 0.0f, -5.0f);
  1742.         XMStoreFloat4x4(&ritem->World, modelScale*modelRot*modelOffset);
  1743.  
  1744.         ritem->TexTransform = MathHelper::Identity4x4();
  1745.         ritem->ObjCBIndex = objCBIndex++;
  1746.         ritem->Mat = mMaterials[mSkinnedMats[i].Name].get();
  1747.         ritem->Geo = mGeometries[mSkinnedModelFilename].get();
  1748.         ritem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1749.         ritem->IndexCount = ritem->Geo->DrawArgs[submeshName].IndexCount;
  1750.         ritem->StartIndexLocation = ritem->Geo->DrawArgs[submeshName].StartIndexLocation;
  1751.         ritem->BaseVertexLocation = ritem->Geo->DrawArgs[submeshName].BaseVertexLocation;
  1752.  
  1753.         // All render items for this solider.m3d instance share
  1754.         // the same skinned model instance.
  1755.         ritem->SkinnedCBIndex = 0;
  1756.         ritem->SkinnedModelInst = mSkinnedModelInst.get();
  1757.  
  1758.         mRitemLayer[(int)RenderLayer::SkinnedOpaque].push_back(ritem.get());
  1759.         mAllRitems.push_back(std::move(ritem));
  1760.     }
  1761. }
  1762.  
  1763. void SkinnedMeshApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  1764. {
  1765.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  1766.     UINT skinnedCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(SkinnedConstants));
  1767.  
  1768.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  1769.     auto skinnedCB = mCurrFrameResource->SkinnedCB->Resource();
  1770.  
  1771.     // For each render item...
  1772.     for(size_t i = 0; i < ritems.size(); ++i)
  1773.     {
  1774.         auto ri = ritems[i];
  1775.  
  1776.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  1777.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  1778.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  1779.  
  1780.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  1781.  
  1782.         cmdList->SetGraphicsRootConstantBufferView(0, objCBAddress);
  1783.  
  1784.         if(ri->SkinnedModelInst != nullptr)
  1785.         {
  1786.             D3D12_GPU_VIRTUAL_ADDRESS skinnedCBAddress = skinnedCB->GetGPUVirtualAddress() + ri->SkinnedCBIndex*skinnedCBByteSize;
  1787.             cmdList->SetGraphicsRootConstantBufferView(1, skinnedCBAddress);
  1788.         }
  1789.         else
  1790.         {
  1791.             cmdList->SetGraphicsRootConstantBufferView(1, 0);
  1792.         }
  1793.  
  1794.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  1795.     }
  1796. }
  1797.  
  1798. void SkinnedMeshApp::DrawSceneToShadowMap()
  1799. {
  1800.     mCommandList->RSSetViewports(1, &mShadowMap->Viewport());
  1801.     mCommandList->RSSetScissorRects(1, &mShadowMap->ScissorRect());
  1802.  
  1803.     // Change to DEPTH_WRITE.
  1804.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
  1805.         D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
  1806.  
  1807.     // Clear the back buffer and depth buffer.
  1808.     mCommandList->ClearDepthStencilView(mShadowMap->Dsv(), 
  1809.         D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  1810.  
  1811.     // Specify the buffers we are going to render to.
  1812.     mCommandList->OMSetRenderTargets(0, nullptr, false, &mShadowMap->Dsv());
  1813.  
  1814.     // Bind the pass constant buffer for the shadow map pass.
  1815.     UINT passCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(PassConstants));
  1816.     auto passCB = mCurrFrameResource->PassCB->Resource();
  1817.     D3D12_GPU_VIRTUAL_ADDRESS passCBAddress = passCB->GetGPUVirtualAddress() + 1*passCBByteSize;
  1818.     mCommandList->SetGraphicsRootConstantBufferView(2, passCBAddress);
  1819.  
  1820.     mCommandList->SetPipelineState(mPSOs["shadow_opaque"].Get());
  1821.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  1822.  
  1823.     mCommandList->SetPipelineState(mPSOs["skinnedShadow_opaque"].Get());
  1824.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::SkinnedOpaque]);
  1825.  
  1826.     // Change back to GENERIC_READ so we can read the texture in a shader.
  1827.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
  1828.         D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
  1829. }
  1830.  
  1831. void SkinnedMeshApp::DrawNormalsAndDepth()
  1832. {
  1833.     mCommandList->RSSetViewports(1, &mScreenViewport);
  1834.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  1835.  
  1836.     auto normalMap = mSsao->NormalMap();
  1837.     auto normalMapRtv = mSsao->NormalMapRtv();
  1838.     
  1839.     // Change to RENDER_TARGET.
  1840.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(normalMap,
  1841.         D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
  1842.  
  1843.     // Clear the screen normal map and depth buffer.
  1844.     float clearValue[] = {0.0f, 0.0f, 1.0f, 0.0f};
  1845.     mCommandList->ClearRenderTargetView(normalMapRtv, clearValue, 0, nullptr);
  1846.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  1847.  
  1848.     // Specify the buffers we are going to render to.
  1849.     mCommandList->OMSetRenderTargets(1, &normalMapRtv, true, &DepthStencilView());
  1850.  
  1851.     // Bind the constant buffer for this pass.
  1852.     auto passCB = mCurrFrameResource->PassCB->Resource();
  1853.     mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
  1854.  
  1855.     mCommandList->SetPipelineState(mPSOs["drawNormals"].Get());
  1856.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  1857.  
  1858.     mCommandList->SetPipelineState(mPSOs["skinnedDrawNormals"].Get());
  1859.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::SkinnedOpaque]);
  1860.  
  1861.     // Change back to GENERIC_READ so we can read the texture in a shader.
  1862.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(normalMap,
  1863.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
  1864. }
  1865. CD3DX12_CPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetCpuSrv(int index)const
  1866. {
  1867.     auto srv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  1868.     srv.Offset(index, mCbvSrvUavDescriptorSize);
  1869.     return srv;
  1870. }
  1871.  
  1872. CD3DX12_GPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetGpuSrv(int index)const
  1873. {
  1874.     auto srv = CD3DX12_GPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  1875.     srv.Offset(index, mCbvSrvUavDescriptorSize);
  1876.     return srv;
  1877. }
  1878.  
  1879. CD3DX12_CPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetDsv(int index)const
  1880. {
  1881.     auto dsv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mDsvHeap->GetCPUDescriptorHandleForHeapStart());
  1882.     dsv.Offset(index, mDsvDescriptorSize);
  1883.     return dsv;
  1884. }
  1885.  
  1886. CD3DX12_CPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetRtv(int index)const
  1887. {
  1888.     auto rtv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
  1889.     rtv.Offset(index, mRtvDescriptorSize);
  1890.     return rtv;
  1891. }
  1892.  
  1893. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> SkinnedMeshApp::GetStaticSamplers()
  1894. {
  1895.     // Applications usually only need a handful of samplers.  So just define them all up front
  1896.     // and keep them available as part of the root signature.  
  1897.  
  1898.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  1899.         0, // shaderRegister
  1900.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1901.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1902.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1903.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1904.  
  1905.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  1906.         1, // shaderRegister
  1907.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1908.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1909.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1910.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1911.  
  1912.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  1913.         2, // shaderRegister
  1914.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1915.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1916.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1917.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1918.  
  1919.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  1920.         3, // shaderRegister
  1921.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1922.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1923.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1924.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1925.  
  1926.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  1927.         4, // shaderRegister
  1928.         D3D12_FILTER_ANISOTROPIC, // filter
  1929.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1930.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1931.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  1932.         0.0f,                             // mipLODBias
  1933.         8);                               // maxAnisotropy
  1934.  
  1935.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  1936.         5, // shaderRegister
  1937.         D3D12_FILTER_ANISOTROPIC, // filter
  1938.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1939.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1940.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  1941.         0.0f,                              // mipLODBias
  1942.         8);                                // maxAnisotropy
  1943.  
  1944.     const CD3DX12_STATIC_SAMPLER_DESC shadow(
  1945.         6, // shaderRegister
  1946.         D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, // filter
  1947.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressU
  1948.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressV
  1949.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressW
  1950.         0.0f,                               // mipLODBias
  1951.         16,                                 // maxAnisotropy
  1952.         D3D12_COMPARISON_FUNC_LESS_EQUAL,
  1953.         D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK);
  1954.  
  1955.     return { 
  1956.         pointWrap, pointClamp,
  1957.         linearWrap, linearClamp, 
  1958.         anisotropicWrap, anisotropicClamp,
  1959.         shadow 
  1960.     };
  1961. }
  1962.  
  1963.